package com.cuit.retryies;

import lombok.extern.slf4j.Slf4j;

import java.util.Random;

@Slf4j
public class ExponetialBackOffRetry implements RetryPolicy{
    private static final int MAX_RETRY_LIMIT = 30;

    private static final int DEFAULT_MAX_SLEEP_MS = Integer.MAX_VALUE;

    private final Random random = new Random();
    private final long baseSleepTime;
    private final int maxRetries;
    private final int maxSleep;


    public ExponetialBackOffRetry(long baseSleepTime, int maxRetries) {
        this(baseSleepTime, maxRetries, DEFAULT_MAX_SLEEP_MS);
    }

    public ExponetialBackOffRetry(long baseSleepTime, int maxRetries, int maxSleep) {
        this.baseSleepTime = baseSleepTime;
        this.maxRetries = maxRetries;
        this.maxSleep = maxSleep;
    }

    @Override
    public boolean allowRetry(int retryCount) {
        if (retryCount < maxRetries){
            return true;
        }
        return false;
    }

    @Override
    public long getSleepTime(int retryCount) {
        if (retryCount < 0){
            throw new IllegalArgumentException("重试次数必须大于0");
        }
        if (retryCount > MAX_RETRY_LIMIT){
            log.error("重试次数已达上限");
            retryCount = MAX_RETRY_LIMIT;
        }
        long sleepMs = baseSleepTime * Math.max(1, random.nextInt(1 << retryCount));
        if (sleepMs > maxSleep){
            log.error("睡眠时间太长，系统重新设置为最长睡眠时间");
            sleepMs = maxSleep;
        }
        return sleepMs;
    }
}
